package com.uxwine.alarm;

import java.util.Calendar;

public class TimeCycle2
{	
//	public static final int TYPE_NONE 			= -1;
	public static final int TYPE_ONCE			= 0;
	public static final int TYPE_DAY			= 1;
	public static final int TYPE_WEEKENDS		= 2;
	public static final int TYPE_WEEKDAYS		= 3;
	public static final int TYPE_MONTH			= 4;
	public static final int TYPE_YEAR			= 5;
	public static final int TYPE_WEEK			= 6;
	public static final int TYPE_HOUR			= 7;
	

	public static final long FLAG_NONE		 	= 0;
	public static final long FLAG_WEEK_SUNDAY	= 1L << 0;
	public static final long FLAG_WEEK_MONDAY 	= 1L << 1;
	public static final long FLAG_WEEK_TUESDAY 	= 1L << 2;
	public static final long FLAG_WEEK_WEDNESDAY= 1L << 3;
	public static final long FLAG_WEEK_THURSDAY	= 1L << 4;
	public static final long FLAG_WEEK_FRIDAY 	= 1L << 5;
	public static final long FLAG_WEEK_SATURDAY	= 1L << 6;
	public static final long FLAG_WEEKDAYS		= FLAG_WEEK_MONDAY | FLAG_WEEK_TUESDAY | FLAG_WEEK_WEDNESDAY | FLAG_WEEK_THURSDAY | FLAG_WEEK_FRIDAY;
	public static final long FLAG_WEEKENDS		= FLAG_WEEK_SUNDAY | FLAG_WEEK_SATURDAY;
	public static final long FLAG_WEEKEVERYDAY	= FLAG_WEEKDAYS | FLAG_WEEKENDS;
	
	
	public static final long FLAG_HOUR_DEFAULT	= 1L;
	public static final long FLAG_HOUR_MAX		= 23L;
	
	private int mnCycle = TYPE_ONCE;
	private long mlFlag = FLAG_NONE;

	public TimeCycle2(int cycle, long flags)
	{
		mnCycle = cycle;
		mlFlag = flags;
	}

	public int getCycle()
	{
		return mnCycle;
	}
	
	public long getFlags()
	{
		return mlFlag;
	}
	
	public void setCycle(int cycle)
	{
		mnCycle = cycle;
	}
	
	public void setFlag(long flag)
	{
		mlFlag = flag;
	}
	
	public void from(TimeCycle2 src)
	{
		mlFlag = src.mlFlag;
		mnCycle = src.mnCycle;
	}

	public boolean setWeekDay(int day, boolean set)
	{
		if(mnCycle != TYPE_WEEK)
			return false;
		
		if (set)
		{
			mlFlag |= (1 << day);
		} 
		else
		{
			mlFlag &= ~(1 << day);
		}
		return true;
	}

	// Returns days of week encoded in an array of booleans.
	public boolean[] getBooleanArray()
	{
		boolean[] ret = new boolean[7];
		for (int i = 0; i < 7; i++)
		{
			ret[i] = isWeekSet(i);
		}
		return ret;
	}

	public boolean isRepeatSet()
	{
		return mnCycle != TYPE_ONCE;
	}
	
	public boolean isOnce()
	{
		return mnCycle == TYPE_ONCE;
	}
	
//	public Calendar getNextAlarm(TimeRecord time)
//	{
//		switch(mnCycle)
//		{
//		case TYPE_ONCE:
//		{
//			//非周期的闹钟，返回一个非空即可
//			final Calendar c = Calendar.getInstance();
//			c.set(Calendar.YEAR, 0);
//			return c;
//		}
//		case TYPE_YEAR: return getByYear(time);
//		case TYPE_MONTH: return getByMonth(time);
//		default: return getByDay(time);
//		}
//	}

	/**
	 * returns number of days from today until next alarm
	 * 
	 * @param c
	 *            must be set to today
	 */
	public int getNextAlarm(Calendar c)
	{
		//none
		if (mnCycle == TYPE_ONCE)
		{
			return -1;
		}

		int today = (c.get(Calendar.DAY_OF_WEEK) + 6) % 7;

		for (int dayCount = 0; dayCount < 7; dayCount++)
		{
			final int day = (today + dayCount) % 7;
			if (isWeekSet(day))
			{
				return dayCount;
			}
		}
		return 0;
	}
	
	public boolean isAviableWeekSet()
	{
		if(mnCycle != TYPE_WEEK)
			return false;
		
		return (mlFlag != FLAG_NONE);
	}
	
	public boolean isWeekEveryDay()
	{
		if(mnCycle != TYPE_WEEK)
			return false;
		
		return (mlFlag == FLAG_WEEKEVERYDAY);
	}
	
//	public Calendar getByDay(TimeRecord time)
//	{
//		// start with now
//        Calendar c = Calendar.getInstance();
//        c.setTimeInMillis(System.currentTimeMillis());
//
//        int hour = time.get(TimeRecord.HOUR);
//        int minute = time.get(TimeRecord.MINUTE);
//        int nowHour = c.get(Calendar.HOUR_OF_DAY);
//        int nowMinute = c.get(Calendar.MINUTE);
//
//        // if alarm is behind current time, advance one day
//        if (hour < nowHour  ||
//            hour == nowHour && minute <= nowMinute) {
//            c.add(Calendar.DAY_OF_YEAR, 1);
//        }
//        c.set(Calendar.HOUR_OF_DAY, hour);
//        c.set(Calendar.MINUTE, minute);
//        c.set(Calendar.SECOND, 0);
//        c.set(Calendar.MILLISECOND, 0);
//
//        int addDays = getNextAlarm(c);
//        if (addDays > 0)
//        	c.add(Calendar.DAY_OF_WEEK, addDays);
//        return c;
//	}
	
//	private Calendar getByMonth(TimeRecord time)
//	{
//		//zzm:下面计算一下周期的闹钟
//        Calendar now = Calendar.getInstance();
//        now.setTimeInMillis(System.currentTimeMillis());
//        Calendar dist = Calendar.getInstance();  
//
//        int day = time.get(TimeRecord.DATE);
//        int hour = time.get(TimeRecord.HOUR);
//        int min = time.get(TimeRecord.MINUTE);
//        
//        int nowYear = now.get(Calendar.YEAR);
//        int nowMonth = now.get(Calendar.MONTH);
//        
//        
//        setWithCheckMonth(dist, nowYear, nowMonth, day, hour, min);
//        
//        if(dist.before(now))
//        {
//        	if(nowMonth == 12)
//        	{
//        		nowYear++;
//        		nowMonth = 1;
//        	}
//        	setWithCheckMonth(dist, nowYear, nowMonth, day, hour, min);
//        }
//        
//        return dist;
//	}
	
//	private static void setWithCheckMonth(Calendar c, int y, int m, int d, int h, int mm)
//	{		
//		//排除了2.29, 2.30, 2.31的情况
//		if(m == 2 && d >= 29)
//		{
//			d = 29;
//			setWithLeap(c, y, m, d, h, mm);
//			return;
//		}
//		
//		if((d == 31) && (m == 4 || m == 6 || m == 9 || m == 11))
//		{
//			d = 30;		
//		}
//		c.set(y, m, d, h, mm);
//	}
	
//	private Calendar getByYear(TimeRecord time)
//	{
//		//zzm:下面计算一下周期的闹钟
//        Calendar now = Calendar.getInstance();
//        now.setTimeInMillis(System.currentTimeMillis());
//        Calendar dist = Calendar.getInstance();        
//
//        int month = time.get(TimeRecord.YEAR);
//        int day = time.get(TimeRecord.DATE);
//        int hour = time.get(TimeRecord.HOUR);
//        int min = time.get(TimeRecord.MINUTE);
//        
//        int nowYear = now.get(Calendar.YEAR);
//        setWithLeap(dist, nowYear, month, day, hour, min);
//        
//        if(dist.before(now))
//        	setWithLeap(dist, nowYear + 1, month, day, hour, min);
//        
//        return dist;
//	}
	
//	private static void setWithLeap(Calendar c, int y, int m, int d, int h, int mm)
//	{
//		c.set(y, m, ((!isLeap(y)) && (m==2 && d == 29)) ? 28 : d, h, m, 0);
//	}
	
	public static boolean isLeap(int year)
	{
		return ((year%4==0)&&(year%100!=0)||(year%400==0));
	}


	public boolean isWeekSet(int day)
	{
		switch(mnCycle)
		{
		case TYPE_DAY:return true;
		case TYPE_WEEKDAYS:return ((FLAG_WEEKDAYS & (1 << day)) > 0);
		case TYPE_WEEKENDS:return ((FLAG_WEEKENDS & (1 << day)) > 0);
		case TYPE_WEEK:return ((mlFlag & (1 << day)) > 0);
		default:return false;
		}
	}
}
